from pprint import pprint
from eolcrawl.database.common_db import CommonDB
from eolcrawl.database.spider_db_models import DB, DownloadLink
import logging
from typing import Tuple, Dict, List, Any

from eolcrawl.spiderutils.common import get_str_md5
from playhouse.shortcuts import model_to_dict  # 添加这行导入

# 配置日志

from eolcrawl.spiderutils.log_helper import get_mylogger
logger = get_mylogger("downloadlink_models",level=logging.INFO)


class DownloadLinkDB(CommonDB):
    """下载链接数据库操作类

    该类提供了对下载链接表(download_link)的各种数据库操作方法
    """

    model = DownloadLink

    @classmethod
    @DB.connection_context()
    def get_download_link(cls, _id, spider_name) -> List[Dict[str, Any]]:
        """根据ID和爬虫名称获取下载链接记录

        Args:
            _id (str): 记录ID
            spider_name (str): 爬虫名称

        Returns:
            List[Dict[str, Any]]: 下载链接记录列表

        Raises:
            Exception: 数据库操作异常
        """
        try:
            query = cls.model.select().where(
                (cls.model._id == _id) & (cls.model.spider_name == spider_name)
            )
            return query.dicts()
        except Exception as e:
            logger.error(f"获取下载链接记录失败: {str(e)}")
            raise

    @classmethod
    @DB.connection_context()
    def insert_download_link(cls, data) -> Tuple[bool, str, Any]:
        """插入下载链接记录

        Args:
            data (dict): 要插入的数据字典

        Returns:
            Tuple[bool, str, Any]: 返回一个元组，包含:
                - bool: 是否成功
                - str: 成功或错误信息
                - Any: 成功时返回新记录的ID，失败时返回None

        Raises:
            Exception: 数据库操作异常
        """
        try:
            # 如果是 DetailContent 实例，转换为字典
            if isinstance(data, cls.model):
                insert_data = model_to_dict(data)
            else:
                insert_data = data

            result = cls.model.insert(insert_data).execute()
            return True, "插入成功", result
        except Exception as e:
            error_msg = f"插入下载链接记录失败: {str(e)}"
            logger.error(error_msg)
            return False, error_msg, None

    @classmethod
    @DB.connection_context()
    def update_download_link(cls, data) -> Tuple[bool, str, int]:
        """更新下载链接记录

        Args:
            data (dict): 要更新的数据字典，必须包含_id和spider_name字段

        Returns:
            Tuple[bool, str, int]: 返回一个元组，包含:
                - bool: 是否成功
                - str: 成功或错误信息
                - int: 更新的记录数，0表示没有记录被更新

        Raises:
            ValueError: 缺少必要的字段
        """
        try:
            if "_id" not in data or "spider_name" not in data:
                raise ValueError("更新数据必须包含_id和spider_name字段")

            result = (
                cls.model.update(data)
                .where(
                    (cls.model._id == data["_id"])
                    & (cls.model.spider_name == data["spider_name"])
                )
                .execute()
            )
            return True, "更新成功" if result > 0 else "没有记录被更新", result
        except Exception as e:
            error_msg = f"更新下载链接记录失败: {str(e)}"
            logger.error(error_msg)
            return False, error_msg, 0

    @classmethod
    @DB.connection_context()
    def delete_download_link(cls, _id, spider_name) -> Tuple[bool, str, int]:
        """删除下载链接记录

        Args:
            _id (str): 记录ID
            spider_name (str): 爬虫名称

        Returns:
            Tuple[bool, str, int]: 返回一个元组，包含:
                - bool: 是否成功
                - str: 成功或错误信息
                - int: 删除的记录数，0表示没有记录被删除

        Raises:
            Exception: 数据库操作异常
        """
        try:
            result = (
                cls.model.delete()
                .where((cls.model._id == _id) & (cls.model.spider_name == spider_name))
                .execute()
            )
            return True, "删除成功" if result > 0 else "没有记录被删除", result
        except Exception as e:
            error_msg = f"删除下载链接记录失败: {str(e)}"
            logger.error(error_msg)
            return False, error_msg, 0

    @classmethod
    @DB.connection_context()
    def get_download_link_by_spider_name(cls, spider_name):
        """根据爬虫名称获取下载链接记录

        Args:
            spider_name (str): 爬虫名称

        Returns:
            dict: 下载链接记录字典

        Raises:
            Exception: 数据库操作异常
        """
        try:
            query = cls.model.select().where(cls.model.spider_name == spider_name)
            return query.dicts()
        except Exception as e:
            logger.error(f"根据爬虫名称获取下载链接记录失败: {str(e)}")
            raise

    @classmethod
    @DB.connection_context()
    def get_download_link_by_url(cls, url):
        """根据URL获取下载链接记录

        Args:
            url (str): 链接URL

        Returns:
            dict: 下载链接记录字典

        Raises:
            Exception: 数据库操作异常
        """
        try:
            query = cls.model.select().where(cls.model.url == url)
            return query.dicts()
        except Exception as e:
            logger.error(f"根据URL获取下载链接记录失败: {str(e)}")
            raise

    @classmethod
    @DB.connection_context()
    def get_download_link_by_status(cls, status):
        """根据状态获取下载链接记录

        Args:
            status (int): 状态值

        Returns:
            dict: 下载链接记录字典

        Raises:
            Exception: 数据库操作异常
        """
        try:
            query = cls.model.select().where(cls.model.status == status)
            return query.dicts()
        except Exception as e:
            logger.error(f"根据状态获取下载链接记录失败: {str(e)}")
            raise

    # 更新状态
    @classmethod
    @DB.connection_context()
    def update_status(cls, url, spider_name, status=1) -> Tuple[bool, str, int]:
        """更新下载链接记录状态

        Args:
            url (str): 记录ID
            spider_name (str): 爬虫名称
            status (int): 状态更新步数，默认为1

        Returns:
            Tuple[bool, str, int]: 返回一个元组，包含:
                - bool: 是否成功
                - str: 成功或错误信息
                - int: 更新的记录数，0表示没有记录被更新

        Raises:
            Exception: 数据库操作异常
        """
        try:
            query = cls.model.update(status=status).where(
                (cls.model.spider_name == spider_name) & (cls.model.url == url)
            )
            return True, "更新成功", query.execute()
        except Exception as e:
            logger.error(f"更新下载链接记录状态失败: {str(e)}")
            return False, f"更新下载链接记录状态失败: {str(e)}", 0

    # 根据spider_name和status获取下载链接记录
    @classmethod
    @DB.connection_context()
    def get_download_link_by_spider_name_and_status(
        cls, spider_name, status
    ) -> List[Dict[str, Any]]:
        """根据爬虫名称和状态获取下载链接记录

        Args:
            spider_name (str): 爬虫名称
            status (int): 状态值

        Returns:
            List[Dict[str, Any]]: 下载链接记录列表，如果没有记录则返回空列表

        Raises:
            Exception: 数据库操作异常
        """
        try:
            query = cls.model.select().where(
                (cls.model.spider_name == spider_name) & (cls.model.status == status)
            )
            return list(query.dicts())  # 显式转换为列表
        except Exception as e:
            error_msg = f"根据爬虫名称和状态获取下载链接记录失败: {str(e)}"
            logger.error(error_msg)
            return []  # 发生异常时返回空列表

    @classmethod
    @DB.connection_context()
    def get_download_link_by_spider_name_and_url(
        cls, spider_name, url
    ) -> List[Dict[str, Any]]:
        """根据爬虫名称和URL获取下载链接记录

        Args:
            spider_name (str): 爬虫名称
            url (str): 链接URL

        Returns:
            List[Dict[str, Any]]: 下载链接记录列表，如果没有记录则返回空列表

        Raises:
            Exception: 数据库操作异常
        """
        try:
            query = cls.model.select().where(
                (cls.model.spider_name == spider_name) & (cls.model.url == url)
            )
            return list(query.dicts())  # 显式转换为列表
        except Exception as e:
            error_msg = f"根据爬虫名称和URL获取下载链接记录失败: {str(e)}"
            logger.error(error_msg)
            return []  # 发生异常时返回空列表

    ##转换item数据为DownloadLink格式数据
    @classmethod
    def convert_item_to_downloadlink(cls, item, name):

        def get_text_value(item, arg):
            return item[arg] if arg in item else ""

        download_link = DownloadLink()
        download_link._id = cls.build_id(item)
        download_link.spider_name = name  # 爬虫名称默认空
        download_link.url = get_text_value(item, "url")  # URL默认空
        download_link.title = get_text_value(item, "title")  # 标题默认空
        download_link.brief = get_text_value(item, "brief")  # 简介默认空
        download_link.father_url = get_text_value(item, "father_url")  # 父链接默认空
        download_link.site_name = get_text_value(item, "site_name")  # 站点名称默认空
        download_link.category = get_text_value(item, "category")  # 分类默认空
        download_link.fawenzihao = get_text_value(
            item, "issue_number"
        )  # 发文字号默认空
        download_link.origin = get_text_value(item, "origin")  # 来源默认空
        download_link.release_date = get_text_value(item, "release_date")  ##发布日期
        download_link.status = 0

        logger.debug(f"download_link: {download_link}")

        return download_link

    @classmethod
    @DB.connection_context()
    def build_id(cls, item):
        """根据ID获取下载链接记录

        Args:
            _id (str): 记录ID

        Returns:
            dict: 下载链接记录字典
        """
        return (
            get_str_md5(item.get("title"))
            if item.get("url") == ""
            else get_str_md5(item.get("url"))
        )


if __name__ == "__main__":
    # instert_data = {
    #     "title": "北京市教育委员会关于印发北京市普通高中学业水平考试实施办法的通知",
    #     "url": "https://jw.beijing.gov.cn/xxgk/2024zcwj/2024xzgfwj/202409/t20240920_3902305.html",
    #     "brief": "",
    #     "status": 0,
    #     "release_date": "",
    #     "category": "行政规范性文件",
    #     "site_name": "北京市教委",
    #     "father_url": "https://jw.beijing.gov.cn/xxgk/2024zcwj/2024xzgfwj/",
    #     "fawenzihao": "2024-09-22",
    #     "origin": "",
    # }

    # ret = DownloadLinkDB.convert_item_to_downloadlink(instert_data, "bjjwlist")
    # pprint(ret)
    pass